
#include "Table.hh"



//------------------------------------------------------
// * Write
//------------------------------------------------------
// Saves the table to a file 
//
template <class T>    
void Table<T>::Write(string &FileName)
{
	ofstream outFile;
 	outFile.open(FileName.c_str());
 	if (outFile.fail()){
 		cout<<FileName<<" file open failed."<<endl;
 		return;
 	}
 	
 	// Save the size
 	outFile<<mRows<<"\t"<<mCols<<endl;
 	
 	// Write out the actual data. 
 	Print(outFile);
 	
 	outFile.close();
}


//------------------------------------------------------
// * Print
//------------------------------------------------------
// Wrapper for Print to allow pointers to be passed in 
// as well as objects.
//
template <class T,class XFMFN> 
void	Print(Table<T> &table,ostream &fout,XFMFN *pf,
						int rowStart,int rowEnd,int colStart,int colEnd)
{					
		XFMFN &f = *(pf);   // Dereference pointer
		Print(table,fout,f,rowStart,rowEnd,colStart,colEnd);
}


// ============================================================================
// === Free standing functions that should be abstracted away from the table 
// === class.  I can envision a set of print utilities, some for 1D iterator
// === classes, others, such as these, for 2D iterator classes.  I am unsure
// === what work is involved in implementing this, so for now this will remain
// === Table specific.  For that matter, it isn't clear to me what other kinds
// === of 2D iterators there might be... VectorTable ... ListTable ... 
// === MapTable ???
  
template <class T,class XFMFN> 
void	Print(Table<T> &table,ostream &fout,XFMFN *pf,
						int rowStart,int rowEnd,int colStart,int colEnd);

template <class T,class XFMFN> 
void	Print(Table<T> &table,ostream &fout,XFMFN &f,
						int rowStart,int rowEnd,int colStart,int colEnd);

/*
//------------------------------------------------------
// * Print
//------------------------------------------------------
// Wrapper for Print to allow pointers to be passed in 
// as well as objects.
//
template <class T,class XFMFN> 
void	Print(Table<T> &table,ostream &fout,XFMFN *pf,
						int rowStart,int rowEnd,int colStart,int colEnd)
{					
		XFMFN &f = *(pf);   // Dereference pointer
		Print(table,fout,f,rowStart,rowEnd,colStart,colEnd);
}
*/


//------------------------------------------------------
// * Print
//------------------------------------------------------
// Prints a table with row and column lables.  Table is padded with spaces 
// to make everything line up.  The functor (function-object) f is applied 
// to each entry in range  [0,rowEnd], [0,colEnd] and resulting string is 
// printed.  The use of a functor allows preservation of state information
// and, so, more complex transformations. 
//
//
template <class T,class XFMFN>
void	Print(Table<T> &t,ostream &fout,XFMFN &f,
						int rowStart,int rowEnd,int colStart,int colEnd)
{
  int r,c;
  const string columnSeparator = "  ";
  
  // Determine which row label is the largest (each label will be padded
  // with spaces to match this size. 
  int maxSize=0;
  for(r = 0;r<t.mRows;r++){
	 int rowSize = t.mRowLabels[r].size();
	 if (rowSize > maxSize) maxSize = t.mRowLabels[r].size();
  }

  // Print initial space corresponding to row label column
  string dummy="";
  PrintSpacePaddedString(fout,maxSize,dummy);
  fout<<columnSeparator;

  // Print the column headings
  for( c= 0;c<t.mCols;c++){
	 fout<<t.mColLabels[c]<<columnSeparator;
  }
  fout<<endl;

  // Print each row..
  for(r = 0;r<t.mRows;r++){
	 // Print row label
	 PrintSpacePaddedString(fout,maxSize,t.mRowLabels[r]);
	 fout<<columnSeparator;
	 // Print data items on the row...
	 for(c = 0;c<t.mCols;c++){
		// Apply the function f to the printout at locations in the range
		if ((r>=rowStart)&&(r<=rowEnd)&&(c>=colStart)&&(c<=colEnd)){
		  string sresult = f(t[r][c]);
		  PrintSpacePaddedString(fout,
										 t.mColLabels[c].size()+
										 columnSeparator.size(),sresult);
		}else{
		  // KJD Should be PrintSpacePadded<T>, or some such...
		  PrintSpacePaddedFloat(fout,t.mColLabels[c].size()+3,t[r][c]);
		}
		fout<<columnSeparator;
	 }
	 fout<<endl;
  }
}


//------------------------------------------------------------------------------
// * RowCmpFunctor
//------------------------------------------------------------------------------
// This is a functor (function-object) class to implement a binary less-than 
// predicate on a table column.  Functors overload operator(), and so look and
// behave like functions to C++.  STL algorithms take functors as arguments, 
// (derived from binary_function, etc., in order to have a consistent interface 
// name).  Functors look like functions to the STL, but unlike functions they  
// may contain state information that persists between function calls. (e.g. 
// mSortCol, mbAscending)   Note that I use the suffix "F" on function 
// class names and the prefix "f" on functor objects.  (kjd)
//
template <class T>
class RowCmpF: public binary_function<T,T,bool>{
public:
	RowCmpF(){mSortCol=0;};
	RowCmpF(int a){mSortCol=a;mbAscending = false;};
	RowCmpF(int a,bool bAscending){mSortCol=a;mbAscending = bAscending;};
		
	bool operator()(T* const &x,T* const &y) 
	{
		T a = x[mSortCol];
		T b = y[mSortCol];
		// Only assumption on the kind of object T used in a table is 
		// that the < operator is defined for T.  
		if (mbAscending){
			return(a>b);
		}else{
			return a<b;
		}
	}

protected:
	int mSortCol;	
	bool mbAscending;

};

//------------------------------------------------------
// * SortRows
//------------------------------------------------------
// Sorts only a subset of rows.  Useful when some rows contain
// summary information of some sort, as is common. 
//
// KJD This desperately needs to sort the row lables as well. 
// There seems no obvious way to do this without changing the 
// datastructure... bundling the row lable in with a TableRow 
// class that gets shuffled around.   Since there is a clear 
// distinction here between Rows and Columns and what you can 
// do with each, it is probably worth writing a transpose method
// that allows one rotate the table contents, sort by row (formerly 
// column), and then transpose back, as a way to sort by column. 
//
//
//   
template <class T>
void
Table<T>::SortRows(int Col,int startRow,int endRow,bool bAscending)
{
   // Sanity check.
	if ((startRow>=0) && (startRow<endRow) && (endRow <= mRows)){
		if ((Col >=0) && (Col < mCols)){	
			RowCmpF<T> fRowCompare(Col,bAscending);

			sort(mTableRows.begin()+startRow,mTableRows.begin()+endRow,fRowCompare);
			//sort(mHandleStart+startRow,mHandleStart+endRow,fRowCompare);
		}
	}
}


//------------------------------------------------------
// * SortRows
//------------------------------------------------------
// Sorts entire table. 
template <class T>
void
Table<T>::SortRows(int Col)
{
   int startRow = 0;
   int endRow = mRows;
	bool bAscending = false;
	SortRows(Col,startRow,endRow,bAscending);
}

//------------------------------------------------------
// * SortRows
//------------------------------------------------------
// Sorts only a subset of rows.  Useful when some rows contain
// summary information of some sort.  
template <class T>
void
Table<T>::SortRows(int Col,int startRow,int endRow)
{
	bool bAscending = false;
 	SortRows(Col,startRow,endRow,bAscending);
}

//------------------------------------------------------
// * Print
//------------------------------------------------------
//
template <class T>
void
Table<T>::Print(ostream &fout)
{
	 if ((mRowLabels.size() == 0) || (mColLabels.size() == 0)){
		PrintNoLabels(fout);
	 }else{
		PrintWithLabels(fout);
	 }	 
}

//------------------------------------------------------
// * PrintNoSpace
//------------------------------------------------------
//
template <class T>    
void Table<T>::PrintNoSpace(ostream &fout)
{
 	for(int row = 0;row <mRows;row++){
 		for(int col = 0;col < mCols;col++){
 			fout<<(*this)[row][col];
 		}
 		fout<<"\n";
 	}	
}



//------------------------------------------------------
// * PrintWithLabels
//------------------------------------------------------
// Prints a table with row and column lables.  Table is
// padded with spaces to make everything line up. 
// KJD Should make columnSeparator an argument. 
//
template <class T>
void
Table<T>::PrintWithLabels(ostream &fout)
{
  int r,c;
  const string columnSeparator = " ";
  
  // Determine which row label is the largest (each label will be padded
  // with spaces to match this size. 
  int maxRowLabelSize=0;
  for(r = 0;r<mRows;r++){
	 if (mRowLabels[r].size()>maxRowLabelSize)
		maxRowLabelSize = mRowLabels[r].size();
  }

  // Print initial space corresponding to row label column
  string dummy=" ";
  PrintSpacePaddedString(fout,maxRowLabelSize+2,dummy);
  fout<<columnSeparator;

  // Print the column headings
  for( c= 0;c<mCols;c++){
	 PrintSpacePaddedString(fout,mColLabels[c].size()+3,mColLabels[c]);
	 fout<<columnSeparator;
  }
  fout<<endl;

  // Print each row..
  for(r = 0;r<mRows;r++){
	 // Print row label
	 PrintSpacePaddedString(fout,maxRowLabelSize,mRowLabels[r]);
	 fout<<columnSeparator;
	 // Print data items on the row...
	 for(c = 0;c<mCols;c++){
		// KJD Should be PrintSpacePadded<T>, or some such...
		PrintSpacePaddedFloat(fout,mColLabels[c].size()+3,(*this)[r][c]);
		fout<<columnSeparator;
	 }
	 fout<<endl;
  }
}

// KJD Another horrible kludge to satisfy Sun Workshop C++ 5.0
// For some reason it doesn't accept set as a type itself, 
// even with the typename keyword.  
typedef set<int,less<int> > intSet;

//------------------------------------------------------
// * PrintColumnSubsetWithLabels
//------------------------------------------------------
// Prints a table with row and column lables.  Table is
// padded with spaces to make everything line up. 
// KJD Should make columnSeparator an argument. 
//
template <class T> 
void
Table<T>::PrintColumnSubsetWithLabels(ostream &fout,intSet &colSet)
{
  int r,c;
  const string columnSeparator = " ";
  
  // Determine which row label is the largest (each label will be padded
  // with spaces to match this size. 
  int maxRowLabelSize=0;
  for(r = 0;r<mRows;r++){
	 if (mRowLabels[r].size()>maxRowLabelSize)
		maxRowLabelSize = mRowLabels[r].size();
  }

  // Print initial space corresponding to row label column
  string dummy=" ";
  PrintSpacePaddedString(fout,maxRowLabelSize+2,dummy);
  fout<<columnSeparator;

  // Print the column headings
  for(c = 0;c < mCols;c++){
	 // If the given column is in the list of columns to print.
	 set<int,less<int> >::iterator sIdx = colSet.find(c);
	 if (sIdx != colSet.end()){
		PrintSpacePaddedString(fout,mColLabels[c].size()+3,mColLabels[c]);
		fout<<columnSeparator;
	 }
  }
  fout<<endl;

  // Print each row..
  for(r = 0;r<mRows;r++){
	 // Print row label
	 PrintSpacePaddedString(fout,maxRowLabelSize,mRowLabels[r]);
	 fout<<columnSeparator;
	 // Print data items on the row...
	 for(c = 0;c<mCols;c++){
		// If the given column is in the list of columns to print, print it...
		set<int,less<int> >::iterator sIdx = colSet.find(c);
		if (sIdx != colSet.end()){
		  // KJD Should be PrintSpacePadded<T>, or some such...
		  PrintSpacePaddedFloat(fout,mColLabels[c].size()+3,(*this)[r][c]);
		  fout<<columnSeparator;
		}
	 }
	 fout<<endl;
  }
}


//------------------------------------------------------
// * PrintNoLabels
//------------------------------------------------------
// Prints a table with row and column lables.  Table is
// padded with spaces to make everything line up. 
// KJD Should make columnSeparator an argument. 
//
template <class T>
void
Table<T>::PrintNoLabels(ostream &fout)
{
  int r,c;
  const string columnSeparator = " ";
  
  int maxSize = 8;

  //  Each row..
  for(r = 0;r<mRows;r++){
	 // Print data items on the row...
	 for(c = 0;c<mCols;c++){
		// KJD Should be PrintSpacePadded<T>, or some such...
		PrintSpacePaddedFloat(fout,maxSize,(*this)[r][c]);
		fout<<columnSeparator;
	 }
	 fout<<endl;
  }
}




//------------------------------------------------------
// * Print
//------------------------------------------------------
// 
template <class T>
void
Table<T>::Print(int r1,int r2,int c1,int c2)
{
  if (r1<0) r1 = 0;
  if (c1<0) c1 = 0;
  if (r2>mRows) r2 = mRows;
  if (c2>mCols) c2 = mCols;

	for(int i = r1;i<r2;i++){
		for(int j = c1;j<c2;j++){
			cout<<(*this)[i][j]<<"\t";
		}
		cout<<endl;
	}	
}

// KJD Removed because it was causing problems for the MakeMaker
// and SWIG compiles.  Not sure why, but I don't use it so out
// it goes. 
//------------------------------------------------------
// * Copy
//------------------------------------------------------
// Makes a copy of the table. 
// 
template<class T>
void 
Table<T>::Copy(Table<T> &TableOut)
{
  TableOut.mRows = this->mRows;
  TableOut.mCols = this->mCols;

  for(int r = 0;r<mRowLabels.size();r++) 
	 TableOut.mRowLabels.push_back(mRowLabels[r]);
  for(int c = 0;c<mColLabels.size();c++) 
	 TableOut.mColLabels.push_back(mColLabels[c]);

  TableOut.Allocate(mRows,mCols);

  for(int rIdx = 0;rIdx < (*this).mRows;rIdx++){
	 for(int cIdx = 0;cIdx < (*this).mCols;cIdx++){
		TableOut[rIdx][cIdx] = (*this)[rIdx][cIdx];
	 }
  }

}


/*
//------------------------------------------------------
// * Write
//------------------------------------------------------
// Saves the table to a file 
//
template <class T>    
void Table<T>::Write(string &FileName)
{
	ofstream outFile;
 	outFile.open(FileName.c_str());
 	if (outFile.fail()){
 		cout<<FileName<<" file open failed."<<endl;
 		return;
 	}
 	
 	// Save the size
 	outFile<<mRows<<"\t"<<mCols<<endl;
 	
 	// Write out the actual data. 
 	Print(outFile);
 	
 	outFile.close();
}
*/

//------------------------------------------------------
// * ReadWithLabels
//------------------------------------------------------
//
//
template <class T>
void Table<T>::ReadWithLabels(char *pFileName)
{
  string temp = pFileName;
  ReadWithLabels(temp);
}


//------------------------------------------------------
// * ReadWithLabels
//------------------------------------------------------
// Reads a table in from a file including column and 
// row lables.  Assumes column and row lables are all 
// present.  Does not need to be told table size in advance. 
//
// KJD: Needs some error handling.  Probably a bit slow too. 
//
template <class T>    
void Table<T>::ReadWithLabels(string &FileName)
{
	ifstream inFile;
 	inFile.open(FileName.c_str(),ios::in);
 	if (inFile.fail()){
 		cout<<FileName<<" file open failed."<<endl;
 		return;
 	}
 	
	// Read in column headings.   
	string tempRowString,tempLabel;

	GetLine(inFile,tempRowString);
	istrstream strStream(tempRowString.c_str());
	strStream>>ws; // consume initial whitespace
	do{
	  strStream>>tempLabel>>ws;
	  mColLabels.push_back(tempLabel);
	}while(!strStream.eof());

	mCols = mColLabels.size(); // save the number of columns found

	do{
	  T* tempRow = new T[mCols+2]; // Make a place to read in rows. 

	  // Get a line
	  GetLine(inFile,tempRowString);

	  // if (!inFile.eof()){
		 istrstream strStream2(tempRowString.c_str()); 

		 // Parse a line
		 strStream2>>ws; // consume initial whitespace
		 strStream2>>tempLabel>>ws; // read in the row label and consume ws
		 mRowLabels.push_back(tempLabel);
		 // Read each column worth of data
		 int col = 0;
		 do{
			T temp;
			strStream2 >> temp >> ws;
			tempRow[col]=temp;
			col++;
		 }while((!strStream2.eof()) && (col < mCols));
		 mTableRows.push_back(tempRow); // add this row to the Table
		 // }
	}while(!inFile.eof());

	mRows = mTableRows.size(); // record table size. 

	inFile.close();
}


//------------------------------------------------------
// * Read
//------------------------------------------------------
// Reads a table in from a file.  For this methods, 
// file contains rows and columns on first line. 
//
// KJD This is inconsistent with ReadWithLables
//
template <class T>    
void Table<T>::Read(string &FileName)
{
	ifstream inFile;
 	inFile.open(FileName.c_str(),ios::in);
 	if (inFile.fail()){
 		cout<<FileName<<" file open failed."<<endl;
 		return;
 	}
	
 	// Read in the size.  Note: ws consumes whitespace in stream. 
 	inFile>>mRows>>ws;
 	inFile>>mCols>>ws;
 	// Make space for it
 	Allocate(mRows,mCols);
 	
 	// Read in the actual data. 
 	char buffer[32000];
 	int  rIdx=0;
 	int  cIdx=0;
 	do{
 		inFile.getline(buffer,32000);
 		// Making the line into a stream makes it easy to skip white space
		istrstream sin(buffer);
		
		// Rely on the >> operator for T to do the conversion from stream 
		// to object of type T.  T will often be a built-in type, of course. 
		T temp;
		while(sin>>temp){
			// Don't want to allow invalid files to kill us...
			if ((rIdx < mRows) && (cIdx < mCols)){
				(*this)[rIdx][cIdx]=temp;
			}else{
				cout<<"!!!! File index out of bounds."<<endl;
			}
			cIdx = cIdx +1;
		}
		cIdx = 0;
		rIdx++;
  }while((cIdx<mCols) && (rIdx<mRows) && !inFile.eof());
 
  inFile.close();
}


//------------------------------------------------------
// * Init
//------------------------------------------------------
//
template <class T>
void
Table<T>::Init(T value)
{
  for(int r = 0;r<mRows;r++){
	 for(int c = 0;c<mCols;c++){
		(*this)[r][c]=value;
	 }
  }
}


//------------------------------------------------------
// * SetLabels
//------------------------------------------------------
// 
template <class T>    
void
Table<T>::SetLabels(vector<string>&RowLabels,vector<string>&ColLabels)
{
  // Erase any existing labels. 
  if (mRowLabels.size()>0) 
	 mRowLabels.erase(mRowLabels.begin(),mRowLabels.end());
  if (mColLabels.size()>0) 
	 mColLabels.erase(mColLabels.begin(),mColLabels.end());

  mRowLabels = RowLabels;
  mColLabels = ColLabels;
}


//------------------------------------------------------
// * GenerateLabels
//------------------------------------------------------
// Generates some default labels by concatenating the row or
// column index to the given row or column prefix.  
//
template <class T>
void
Table<T>::GenerateLabels(string &RowPrefix,string &ColPrefix)
{
	char buf[500];
	for(int i = 0;i<mRows;i++){
		sprintf(buf,"%d",i);
		string rowTemp = RowPrefix + buf ;
		mRowLabels.push_back(rowTemp);
		for(int j = 0;j<mCols;j++){	
			sprintf(buf,"%d",j);
			string colTemp = ColPrefix+buf;
			mColLabels.push_back(colTemp);
		}
	}
}


//------------------------------------------------------
// * FindColumnWithLabel
//------------------------------------------------------
// 
//
template <class T>
int
Table<T>::FindColumnWithLabel(string &label)
{
  vector<string>::iterator q;
  q = find(mColLabels.begin(),mColLabels.end(),label);
  return((int)(q - mColLabels.begin()));
}


//------------------------------------------------------
// * FindRowWithLabel
//------------------------------------------------------
// 
//
template <class T>
int
Table<T>::FindRowWithLabel(string &label)
{
  vector<string>::iterator q;
  q = find(mRowLabels.begin(),mRowLabels.end(),label);
  return((int)(q - mRowLabels.begin()));
}



//------------------------------------------------------
// * Allocate
//------------------------------------------------------
// 
template <class T>    
void
Table<T>::Allocate(int NumRows,int NumCols)
{
  T* tempTPtr=NULL;

  for(int r = 0;r<NumRows;r++){
	 mTableRows.push_back(tempTPtr);
	 mTableRows[r] = new T[NumCols];
  }
  mRows = NumRows;
  mCols = NumCols;
}


//------------------------------------------------------
// * RemoveRow
//------------------------------------------------------
// This should be PopRowBack, or some sort, to indicate how
// row will be added. 
//
template <class T>
void
Table<T>::RemoveRow()
{
  if (mRows > 0){
	 if (mTableRows[mTableRows.size()-1] != NULL){
		delete [] mTableRows[mTableRows.size()-1];
	 }else{
		cout<<"NULL pointer"<<endl;
	 }
	 mTableRows.pop_back();
	 mRows--;
  }
}


//------------------------------------------------------
// * AddRow
//------------------------------------------------------
// KJD This should be PushRowBack, or some sort, to indicate
// how row will be added.  
//
template <class T>
void
Table<T>::AddRow()
{
  if (mCols > 0){
	 T* tempTPtr = NULL;
	 mTableRows.push_back(tempTPtr);
	 mTableRows[mTableRows.size()-1] = new T[mCols];
	 mRows++;
  }else{
	 cout<<"Table: Can't add row with no columns defined.\n";
  }
}

//------------------------------------------------------
// * AddRow
//------------------------------------------------------
//
template <class T>
void
Table<T>::AddRow(string RowName)
{
  AddRow();
  mRowLabels.push_back(RowName);
}


//------------------------------------------------------
// * DeAllocate
//------------------------------------------------------
// 
template <class T>    
void
Table<T>::DeAllocate()
{	

  // Do nothing if there is nothing there
  if (mTableRows.size() <=0) return;

  for(int i = 0;i<mRows;i++){
	 // Verify that each pointer is non-null 
	 if (mTableRows[i] != NULL){
		delete [] mTableRows[i];
	 }
  }

  // Now erase the vector of pointers
  mTableRows.clear();

  mRows = 0;
  mCols = 0;
}





//-------------------------------------------------------------------

// BEGIN KNOWN GOOD CODE
#if 0
//------------------------------------------------------
// * Allocate
//------------------------------------------------------
// 
template <class T>    
void
Table<T>::Allocate(int NumRows,int NumCols)
{
  mHandleStart = NULL;
  mHandleStart = new T*[NumRows];
  for(int r = 0;r<NumRows;r++){
	 mHandleStart[r] = NULL;		// If new fails, this will prevent delete
	 mHandleStart[r] = new T[NumCols];
  }
  mRows = NumRows;
  mCols = NumCols;
}


//------------------------------------------------------
// * DeAllocate
//------------------------------------------------------
// 
template <class T>    
void
Table<T>::DeAllocate()
{	
	// Important safety measure, as table may never have 
	// been allocated. 
	if (mHandleStart != NULL){
		for(int i = 0;i<mRows;i++){
			if (mHandleStart[i] != NULL){
				delete [] mHandleStart[i];
			}
		}
		delete [] mHandleStart;
	}
	mRows = 0;
	mCols = 0;
}
#endif
// END KNOWN GOOD CODE

